package com.cfpamf.ms.insur.pay.facade.util;

import com.cfpamf.ms.insur.pay.facade.constant.PayConstant;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.MapUtils;

import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;

/**
 * Create By zhengjing on 2019-10-21 14:49
 */
@Slf4j
public final class SignUtil {


    public static void validSign(Map<String, Object> data, String sign, String key) {

        log.debug("开始校验名{}:{}==>{}", key, data, sign);
        if (!Objects.equals(MD5(data, key), sign)) {
            throw new IllegalStateException("签名校验失败:" + sign);
        }
        log.debug("校验签名成功");
    }

    /**
     * 生成 MD5
     * 将所有map中的数据按key的排序之后 value
     * 转换成 key=value 然后用 & 拼接 number对象【只序列化时不带引号的】只取int部分
     *
     * @param data 待处理数据
     * @return MD5结果
     */
    public static String MD5(Map<String, Object> data, String key) {

        if (MapUtils.isEmpty(data))
            throw new IllegalArgumentException("加密参数为空！");
        Set<String> keySet = data.keySet();
        String[] keyArray = keySet.toArray(new String[keySet.size()]);
        Arrays.sort(keyArray);

        StringJoiner sj = new StringJoiner("&");
        for (String k : keyArray) {
            if (k.equals(PayConstant.FIELD_SIGN)) {
                continue;
            }
            Object val = data.get(k);
            if (val instanceof Number) {
                val = ((Number) val).intValue();
            }
            if (Objects.nonNull(val) && val.toString().trim().length() > 0)// 参数值为空，则不参与签名
                sj.add(k + "=" + val.toString().trim());
        }
        // key拼接在最后
        sj.add(PayConstant.FIELD_SIGN_KEY + "=" + key);
        log.debug("签名字符为:{}", sj.toString());
        return MD5(sj.toString());
    }

    /**
     * 生成 MD5
     *
     * @param data 待处理数据
     * @return MD5结果
     */
    public static String MD5(String data) {
        MessageDigest md = null;
        try {
            md = MessageDigest.getInstance("MD5");
            byte[] array = md.digest(data.getBytes(StandardCharsets.UTF_8));
            StringBuilder sb = new StringBuilder();
            for (byte item : array) {
                sb.append(Integer.toHexString((item & 0xFF) | 0x100).substring(1, 3));
            }
            return sb.toString().toUpperCase();
        } catch (NoSuchAlgorithmException ex) {
            throw new IllegalStateException("Could not find MessageDigest with algorithm \"" + data + "\"", ex);
        }

    }
}
